/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package biofilter.filters;

import biofilter.exceptions.InvalidRecordException;
import biofilter.factories.MappedPositionFactory;
import biofilter.records.FileNameRecord;
import biofilter.records.Record;
import biofilter.records.BowTieRecord;
import biofilter.sources.RecordsFile;
import biofilter.sources.RecordsSourceIF;
import biofilter.util.MappedPosition;

/**
 * IMPORTANT!  THIS FILE NEEDS REFACTORING!!!  IT NEEDS TO BE CODED LIKE RecordsFile2GFF!
 * However, currently Mapper454HistoPipeline uses this, so we must ensure that still works when this is done!
 *
 *
 * This filter takes FileNameRecord objects and returns mappedpositions records.
 * for each FileNameRecord, it performs a split; thus returning many bowtie records
 * for one FileNameRecord
 * 
 * 
 * This class is a more general version of classes like RecordsFile2BowtieRecord
 * the primary difference is that here, we wish to be able to make ANY mapped position type record
 * from the lines in a file.
 * @author Daniel Quest
 * @date Feb 23 2010
 */
public class RecordsFile2MappedPosition extends SimpleFilter {

    public RecordsFile2MappedPosition(){
       super();
    }
    /**
     *
     * @param MappedPositionType
     * A MappedPositionType is anything that implements a mapped position interface
     * examples include:
     * biofilter.records.GFFRecord
     * biofilter.records.Mapper454Record
     * biofilter.records.BlastTabRecord
     * biofilter.records.BowTieRecord
     */
    public RecordsFile2MappedPosition(String MappedPositionType){
        super();
        setMappedPositionType(mappedPositionType);
    }
    private MappedPositionFactory mpf = new MappedPositionFactory();
    private String mappedPositionType = null;
    public String getMappedPositionType() {
        return mappedPositionType;
    }

    public void setMappedPositionType(String mappedPositionType) {
        this.mappedPositionType = mappedPositionType;
    }

    protected Record transformRecord(Record r) throws InvalidRecordException {
        if (!(r instanceof FileNameRecord)) {
            throw new RuntimeException("type mismatch, expected FileNameRecord");
        }if(r == null){
            throw new RuntimeException("FileNameRecord is null!");
        }

        //System.err.println(r.get());
        //System.err.println(this.getMappedPositionType());
        Record mappedPosition = mpf.getMappedPosition(mappedPositionType);
        mappedPosition.set(r.get());
        return mappedPosition;

    }

    /**
     * To get the original record, maintain the original records and transfomred
     * records lists, and to call transformRecord to transform the record
     * @return Record - the transformed record
     */
    RecordsFile singleLineRecords = null;
    @Override
    public Record getRecord() throws InvalidRecordException {
        this.transformedRecord = null;
        if (!(this.source instanceof RecordsFile)){
            throw new InvalidRecordException("Source to the RecordsFile2MappedPosition filter must be a RecordsFile");
        }
        if (this.source == null){
            throw new InvalidRecordException("Source to RecordsFile2MappedPosition filter can not be null!");
        }

        //if we are currently at the end of a set of records to process, e.g. the end of a file
        //or we don't currently have a set of records to process
        //then setup the RecordsFile
        if ( (singleLineRecords == null || singleLineRecords.eof() ) && !this.source.eof() ){
            String filename = this.source.getRecord().get(); //get the next filename
            singleLineRecords = new RecordsFile(filename, "biofilter.records.FileNameRecord");
        }
        
        if ( !singleLineRecords.eof() ){
            this.originalRecord = singleLineRecords.getRecord();
            if ( this.originalRecord != null) {
                this.transformedRecord = this.transformRecord( this.originalRecord );
            }
        }

        return this.transformedRecord;
    }
    
    @Override
    public boolean eof() {
        if ( this.singleLineRecords.eof() && this.source.eof() ) return true;
        else return false;
    }

    public Record peek() throws InvalidRecordException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
